Como generar números (pseudo)-aleatorios en microcontroladores AVR.
Usaremos el timer1 del microcontrolador para que cuente entre 0 y 65535, cuando se produzca una entrada del usuario obtendremos el valor del timer1 para conseguir el numero pseudo-aleatorio, y hacemos los calculos (módulo y sumar), para que el valor esté entre el rango que quiera el usuario.
En este ejemplo el numero resultante se muestra en binario usando leds.
IMPORTANTE: es imprescindible que la función get_random() sea llamada en base a una entrada del usuario, si se llama de manera automátizada desde el código se perderá entropia y los numeros podrían ser mas predecibles.
#include <avr/io.h>
#include <util/delay.h>
#include <avr/interrupt.h>
void timer1_init() {
TCCR1B |= (1 << WGM12); // Modo CTC
TCCR1B |= (1 << CS10); // Sin preescaler
OCR1A = 65535;
}
int get_random(int a, int b){
int numberDiff = b - a + 1;
return (TCNT1 % numberDiff) + a; //Usamos el timer1 para obtener un valor y hacemos los calculos para que esté en el rango que se ha indicado
}
ISR(INT0_vect) {
PORTB = get_random(5,16);
_delay_ms(500);
EIFR |= (1 << INTF0); //eliminamos posibles interrupciones generadas durante el ISR
}
int main(void) {
DDRB = 0xFF; //Todos los puertos del registro B como salida
PORTD |= (1 << PD2); // pull-up resistor en PD2
EIMSK |= (1 << INT0); //Activamos INT0 para interrupciones
EICRA |= (1 << ISC00); //Generamos interrupción cuando haya un cambio en el puerto
sei(); //Activamos interrupciones globalmente
timer1_init(); // Inicializar Timer1
while (1) {
PORTB = 0x00; //Apagamos leds
}
}
AVR | Random